﻿using System;
using UnityEngine;

namespace winS.Unity
{
    /// <summary>
    /// 更新器
    /// </summary>
    public static class Updater
    {
        private static readonly FunctionUpdater functionUpdater;

        static Updater()
        {
            GameObject updaterGameObject = new GameObject("Updater") { hideFlags = HideFlags.HideInHierarchy };
            functionUpdater = updaterGameObject.AddComponent<FunctionUpdater>();
            UnityEngine.Object.DontDestroyOnLoad(updaterGameObject);
        }

        public static UpdateHandle AddUpdate(Action function)
        {
            return AddUpdate(_ => function());
        }
        public static UpdateHandle AddUpdate(Action<float> function)
        {
            return AddUpdateWithName(function, null);
        }
        public static UpdateHandle AddUpdateWithName(Action function, string name)
        {
            return AddUpdateWithName(_ => function(), name);
        }
        public static UpdateHandle AddUpdateWithName(Action<float> function, string name)
        {
            UpdateFunction updateFunction = new UpdateFunction(function);
            updateFunction.name = name;
            UpdateHandle updateHandle = new UpdateHandle(updateFunction);
            functionUpdater.waitAddUpdateFunctionList.Add(updateFunction);
            return updateHandle;
        }
        public static UpdateHandle AddUpdate(Action<float> function, GameObject owner)
        {
            if (!owner.activeInHierarchy) throw new Exception($"[{nameof(Updater)}.{nameof(AddUpdate)}] 所有者必须处于完全激活状态才可以添加");
            if (!owner.TryGetComponent(out HandleOwner handleOwner)) handleOwner = owner.AddComponent<HandleOwner>();
            UpdateHandle updateHandle = AddUpdate(function);
            handleOwner.AddHandle(updateHandle);
            return updateHandle;
        }

        public static LateUpdateHandle AddLateUpdate(Action function)
        {
            return AddLateUpdate(_ => function());
        }
        public static LateUpdateHandle AddLateUpdate(Action<float> function)
        {
            LateUpdateFunction lateUpdateFunction = new LateUpdateFunction(function);
            LateUpdateHandle lateUpdateHandle = new LateUpdateHandle(lateUpdateFunction);
            functionUpdater.waitAddLateUpdateFunctionList.Add(lateUpdateFunction);
            return lateUpdateHandle;
        }
        public static LateUpdateHandle AddLateUpdate(Action<float> function, GameObject owner)
        {
            if (!owner.activeInHierarchy) throw new Exception($"[{nameof(Updater)}.{nameof(AddLateUpdate)}] 所有者必须处于完全激活状态才可以添加");
            if (!owner.TryGetComponent(out HandleOwner handleOwner)) handleOwner = owner.AddComponent<HandleOwner>();
            LateUpdateHandle lateUpdateHandle = AddLateUpdate(function);
            handleOwner.AddHandle(lateUpdateHandle);
            return lateUpdateHandle;
        }

        public static DelayCallHandle AddDelayCall(float delay, Action function)
        {
            DelayCallFunction delayCallFunction = new DelayCallFunction(delay, function);
            DelayCallHandle delayCallHandle = new DelayCallHandle(delayCallFunction);
            functionUpdater.waitAddDelayCallFunctionList.Add(delayCallFunction);
            return delayCallHandle;
        }
        public static DelayCallHandle AddDelayCall(float delay, Action function, GameObject owner)
        {
            if (!owner.activeInHierarchy) throw new Exception($"{nameof(Updater)}.{nameof(AddDelayCall)}: 协程所有者必须处于完全激活状态才可以添加");
            if (!owner.TryGetComponent(out HandleOwner handleOwner)) handleOwner = owner.AddComponent<HandleOwner>();
            DelayCallHandle delayCallHandle = AddDelayCall(delay, function);
            handleOwner.AddHandle(delayCallHandle);
            return delayCallHandle;
        }
        public static RepeatCallHandle AddRepeatCall(float interval, Action function)
        {
            RepeatCallFunction repeatCallFunction = new RepeatCallFunction(interval, function);
            RepeatCallHandle repeatCallHandle = new RepeatCallHandle(repeatCallFunction);
            functionUpdater.waitAddRepeatCallFunctionList.Add(repeatCallFunction);
            return repeatCallHandle;
        }
        public static RepeatCallHandle AddRepeatCall(float interval, Action function, GameObject owner)
        {
            if (!owner.activeInHierarchy) throw new Exception($"{nameof(Updater)}.{nameof(AddRepeatCall)}: 协程所有者必须处于完全激活状态才可以添加");
            if (!owner.TryGetComponent(out HandleOwner handleOwner)) handleOwner = owner.AddComponent<HandleOwner>();
            RepeatCallHandle repeatCallHandle = AddRepeatCall(interval, function);
            handleOwner.AddHandle(repeatCallHandle);
            return repeatCallHandle;
        }

        internal static void RemoveUpdate(UpdateFunction function)
        {
            function.functionState = FunctionState.WaitForRemove;
            functionUpdater.waitRemoveUpdateFunctionList.Add(function);
        }
        internal static void RemoveLateUpdate(LateUpdateFunction function)
        {
            function.functionState = FunctionState.WaitForRemove;
            functionUpdater.waitRemoveLateUpdateFunctionList.Add(function);
        }
        internal static void RemoveDelayCall(DelayCallFunction function)
        {
            function.functionState = FunctionState.WaitForRemove;
            functionUpdater.waitRemoveDelayCallFunctionList.Add(function);
        }
        internal static void RemoveRepeatCall(RepeatCallFunction function)
        {
            function.functionState = FunctionState.WaitForRemove;
            functionUpdater.waitRemoveRepeatCallFunctionList.Add(function);
        }
    }
}